
/* GCSx
** EXCEPTION.H
**
** GCSx exception classes
*/

/*****************************************************************************
** Copyright (C) 2003-2006 Janson
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
** 
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
*****************************************************************************/

#ifndef __GCSx_EXCEPTION_H_
#define __GCSx_EXCEPTION_H_

// Exceptions are only used for non-fatal errors; fatal errors simply
// abort gracelessly (i.e. system error box) for simplicity
class BaseException {
protected:
    void setDetails(const char* base, va_list arglist);
    
    enum {
        DETAILS_SIZE = 160,
    };

public:
    char details[DETAILS_SIZE];
    
    BaseException();
};

// Non-fatal video execptions only occur during setting/changing video modes or
// resolutions, etc.- video problems during normal graphic activity are fatal
class VideoException : public BaseException {
public:
    VideoException(const char* base, ...);
};

// File exceptions should cause an abort of whatever was being loaded
class FileException : public BaseException {
public:
    FileException(const char* base, ...);
};

// Compile assertion- throws CompileException if needed
// Currently tied to NDEBUG but can be tied to anything else
#ifndef NDEBUG
#define COMPILEASSERT
#endif

#ifdef COMPILEASSERT
// Compile exceptions should cause an abort of compilation and discarding of bytecode
class CompileException : public BaseException {
public:
    CompileException(const char* base, ...);
};

#define compileAssert(e)    if (!(e)) throw CompileException("Internal compiler error: %s at %s, %d", #e, __FILE__, __LINE__)
#define bytecodeAssert(e)   if (!(e)) throw CompileException("Internal bytecode error: %s at %s, %d", #e, __FILE__, __LINE__)
#define tokenizerAssert(e)  if (!(e)) throw CompileException("Internal tokenizer error: %s at %s, %d", #e, __FILE__, __LINE__)
#else
#define compileAssert(x)    ((void)0)
#define bytecodeAssert(x)   ((void)0)
#define tokenizerAssert(x)  ((void)0)
#endif

// Interpreter assertion- throws InterpretException if needed
// Currently tied to NDEBUG but can be tied to anything else
#ifndef NDEBUG
#define INTERPRETASSERT
#endif

#ifdef INTERPRETASSERT
// Interpreter exceptions should cause an abort of running script
class InterpretException : public BaseException {
public:
    InterpretException(const char* base, ...);
};

#define interpretAssert(e)    if (!(e)) throw InterpretException("Runtime interpreter error: %s at %s, %d", #e, __FILE__, __LINE__)
#else
#define interpretAssert(x)    ((void)0)
#endif

// Undo exceptions signify cancelling whatever action was being done
class UndoException : public BaseException {
public:
    UndoException();
};

// Instead of using exception specifications, we use these macros.
// This allows us to define which functions throw what exceptions,
// or ones where we're unsure, or nothing is thrown, but we don't
// have to use actual exception specifications which are bad(tm)
#define throw_Video
#define throw_File
#define throw_Compile
#define throw_Interpret
#define throw_Undo
#define throw_int

#endif
